home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: Camelot
/
Camelot 134 (1991-10)(Swedish User Group of Amiga)(SE)(PD)[WB].zip
/
Camelot 134 (1991-10)(Swedish User Group of Amiga)(SE)(PD)[WB].adf
/
GIFMachine
/
Sources
/
writeiff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-01
|
10KB
|
452 lines
/* Copyright 1990 by Christopher A. Wichura.
See file GIFMachine.doc for full description of rights.
*/
#include "GIFMachine.h"
#include <iff/ILBM.h>
#include <libraries/iffparse.h>
#include <graphics/displayinfo.h>
#include <graphics/view.h>
#include <dos/datetime.h>
#include <clib/iffparse_protos.h>
extern struct Library *IFFParseBase;
#include <pragmas/iffparse_lib.h>
extern struct GIFdescriptor gdesc;
EXTERNBITPLANE;
extern struct MinList CommentList;
extern char *AbortMsg;
extern UWORD *SHAMmem;
BYTE *PlaneBuf;
extern BOOL DisplayCounts;
BOOL Laced;
UBYTE *Planes[24];
static UBYTE CompBuf[256];
static ULONG PlanePos;
/* our version number stuff */
extern ULONG __far Version;
extern ULONG __far Revision;
BOOL WriteIFF(char *tofile, BOOL DeepFlag)
{
register struct IFFHandle *iff;
register int index;
register ULONG ChunkSize;
register UWORD current;
struct DisplayInfo DspInfo;
char WrittenBy[40];
ColorRegister ColourBuf;
BitMapHeader bmh;
PutStr("...Writing IFF file.");
if (!GetDisplayInfoData(NULL, (UBYTE *)&DspInfo, sizeof(struct
DisplayInfo), DTAG_DISP, (Laced ? HAMLACE_KEY : HAM_KEY))) {
PutStr("\n......Error trying to obtain display info.\n");
return TRUE;
}
if (!(iff = AllocIFF())) {
PutStr("\n......Error allocating IFF handle.\n");
return TRUE;
}
if (!(iff->iff_Stream = Open(tofile, MODE_NEWFILE))) {
MyPrintf("\n......Error %ld trying to create %s.", IoErr(), tofile);
goto EndWriteIFF;
}
InitIFFasDOS(iff);
if (OpenIFF(iff, IFFF_WRITE)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
if (PushChunk(iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
if (PushChunk(iff, 0L, MAKE_ID('A','N','N','O'), IFFSIZE_UNKNOWN)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
MySPrintf(WrittenBy, "Written by GIFMachine v%ld.%ld on ", Version, Revision);
if (WriteChunkBytes(iff, (APTR)&WrittenBy, strlen(WrittenBy)) != strlen(WrittenBy)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
{
struct DateTime dat;
char Date[LEN_DATSTRING + 1];
int DateLength;
DateStamp(&dat.dat_Stamp);
dat.dat_Format = FORMAT_DOS;
dat.dat_Flags = 0;
dat.dat_StrDay = NULL;
dat.dat_StrDate = Date;
dat.dat_StrTime = NULL;
memset(Date, 0, LEN_DATSTRING + 1);
DateToStr(&dat);
DateLength = strlen(Date) + 1;
if (WriteChunkBytes(iff, (APTR)&Date, DateLength) != DateLength) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
}
if (PopChunk(iff)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
{
struct CommentNode *cn;
char ANNObuf[1];
#define C_BLOCK_ID "GIF Comment Block: "
ANNObuf[0] = 0;
while (cn = (struct CommentNode *)RemHead((struct List *)&CommentList)) {
if (PushChunk(iff, 0L, MAKE_ID('A','N','N','O'), IFFSIZE_UNKNOWN)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
if (WriteChunkBytes(iff, (APTR)C_BLOCK_ID, strlen(C_BLOCK_ID)) != strlen(C_BLOCK_ID)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
if (WriteChunkBytes(iff, (APTR)cn->cn_Comment, cn->cn_CommentLength) != cn->cn_CommentLength) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
if (WriteChunkBytes(iff, (APTR)ANNObuf, 1) != 1) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
if (PopChunk(iff)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
}
}
if (PushChunk(iff, 0L, ID_BMHD, sizeof(BitMapHeader))) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
bmh.w = (gdesc.gd_Width & 1) ? gdesc.gd_Width + 1 : gdesc.gd_Width;
bmh.h = (gdesc.gd_Height & 1) ? gdesc.gd_Height + 1 : gdesc.gd_Height;
bmh.x = bmh.y = 0;
bmh.nPlanes = (DeepFlag ? 24 : 6);
bmh.masking = mskNone;
bmh.compression = cmpByteRun1;
bmh.pad1 = 0;
bmh.transparentColor = 0;
bmh.xAspect = DspInfo.Resolution.x;
bmh.yAspect = DspInfo.Resolution.y;
bmh.pageWidth = 320;
bmh.pageHeight = (Laced ? 400 : 200);
if (WriteChunkBytes(iff, (APTR)&bmh, sizeof(BitMapHeader)) != sizeof(BitMapHeader)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
if (PopChunk(iff)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
if (PushChunk(iff, 0L, ID_CAMG, 4)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
{
LONG CAMGbuf[1];
CAMGbuf[0] = (DeepFlag ? 0 : HAM) | (Laced ? LACE : 0);
if (WriteChunkBytes(iff, (APTR)&CAMGbuf, 4) != 4) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
}
if (PopChunk(iff)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
if (!DeepFlag) {
if (PushChunk(iff, 0L, ID_CMAP, 16 * 3)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
for (index = 0; index < 16; index++) {
current = SHAMmem[index];
ColourBuf.red = (current >> 4) & 0xF0;
ColourBuf.green = current & 0xF0;
ColourBuf.blue = (current & 15) << 4;
if (WriteChunkBytes(iff, (APTR)&ColourBuf, sizeofColorRegister) != sizeofColorRegister) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
}
if (PopChunk(iff)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
ChunkSize = (Laced ? gdesc.gd_Height / 2 : gdesc.gd_Height) * 16 * sizeof(UWORD);
if (PushChunk(iff, 0L, MAKE_ID('S','H','A','M'), IFFSIZE_UNKNOWN)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
{
UWORD SHAMversion[1];
SHAMversion[0] = 0;
if (WriteChunkBytes(iff, (APTR)&SHAMversion, sizeof(UWORD)) != sizeof(UWORD)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
}
if (WriteChunkBytes(iff, (APTR)SHAMmem, ChunkSize) != ChunkSize) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
if (gdesc.gd_Height & 1) {
UWORD BlankSHAM[16];
memset((char *)BlankSHAM, 0, sizeof(BlankSHAM));
if (WriteChunkBytes(iff, (APTR)BlankSHAM, sizeof(BlankSHAM)) != sizeof(BlankSHAM)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
}
if (PopChunk(iff)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
} /* end if (!DeepFlag) */
if (PushChunk(iff, 0L, ID_BODY, IFFSIZE_UNKNOWN)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
/* now we actually write the body chunk out */
{
register int plane;
register int col;
register UWORD x;
register UWORD y;
register int index;
UBYTE PlaneMask, ColMask;
UWORD Cols;
if (DisplayCounts)
PutStr("\n......Line ");
else
PutStr("\n......Working");
Flush(Output());
Cols = (bmh.w + 7) / 8;
if (IS_ODD(Cols))
Cols++;
for (y = 0; y < ((gdesc.gd_Height & 1) ? gdesc.gd_Height + 1 : gdesc.gd_Height) ; y++) {
if (DisplayCounts)
MyPrintf("%5ld", y);
if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
MyPrintf("\n%s", AbortMsg);
CloseIFF(iff);
Close(iff->iff_Stream);
FreeIFF(iff);
MyExit(ABORTEXITVAL);
}
if (y != gdesc.gd_Height)
for (index = 0; index < (DeepFlag ? 3 : 1); index++) {
col = 0;
ColMask = 1L << 7;
for (x = 0; x < gdesc.gd_Width; x++) {
if (DeepFlag)
current = *((UBYTE *)&BitPlane[y][x]+index);
else
current = GetValue(x, y);
PlaneMask = 1;
for (plane = 0; plane < (DeepFlag ? 8 : 6); plane++) {
if (current & PlaneMask)
Planes[plane + index * 8][col] |= ColMask;
PlaneMask <<= 1;
}
if (ColMask == 1) {
ColMask = 1L << 7;
col++;
} else
ColMask >>= 1;
}
}
/* now we need to compress the scan line */
{
register BOOL state;
register char c;
register char lastc;
register UWORD nbuf;
register UWORD rstart;
for (plane = 0; plane < (DeepFlag ? 24 : 6); plane++) {
CompBuf[0] = lastc = c = Planes[plane][0];
state = FALSE;
PlanePos = rstart = 0;
nbuf = col = 1;
while (col < Cols) {
CompBuf[nbuf++] = c = Planes[plane][col++];
switch (state) {
case FALSE:
if (nbuf > 128) {
OutDump(nbuf - 1);
CompBuf[0] = c;
nbuf = 1;
rstart = 0;
break;
}
if (c == lastc) {
if (nbuf - rstart >= 3) {
if (rstart > 0)
OutDump(rstart);
state = TRUE;
} else if (rstart == 0)
state = TRUE;
} else
rstart = nbuf - 1;
break;
case TRUE:
if ((c != lastc) || (nbuf - rstart > 128)) {
OutRun(nbuf - 1 - rstart, lastc);
CompBuf[0] = c;
nbuf = 1;
rstart = 0;
state = FALSE;
}
break;
}
lastc = c;
}
switch (state) {
case FALSE:
OutDump(nbuf);
break;
case TRUE:
OutRun(nbuf - rstart, lastc);
break;
}
/* now write the compressed plane out */
if (WriteChunkBytes(iff, (APTR)PlaneBuf, PlanePos) != PlanePos) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
memset((char *)Planes[plane], 0, Cols);
}
}
if (DisplayCounts)
MyPrintf("\x1B[5D");
}
}
if (PopChunk(iff)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
if (PopChunk(iff)) {
PutStr("\n......Error writing to IFF.\n");
goto EndWriteIFF;
}
MyPrintf("\x1B[%ldD\x1B[KWritten.\n", (DisplayCounts ? 5 : 7));
EndWriteIFF:
CloseIFF(iff);
if (iff->iff_Stream)
Close(iff->iff_Stream);
FreeIFF(iff);
return TRUE;
}
void OutDump(int nn)
{
register int index;
PlaneBuf[PlanePos++] = nn - 1;
for (index = 0; index < nn; index++)
PlaneBuf[PlanePos++] = CompBuf[index];
}
void OutRun(int nn, int cc)
{
PlaneBuf[PlanePos++] = -(nn - 1);
PlaneBuf[PlanePos++] = cc;
}